#include "StdAfx.h"
#include "Graphics.h"
#include "Texture.h"

namespace Renderer
{

	Texture::Texture()
	{
		graphics = NULL;
		texture = NULL;
		width = height = 0;
	}
	Texture::~Texture()
	{
		Free();
	}

	IDirect3DTexture9* Texture::GetTextureCOM()
	{
		return texture;
	}

	bool Texture::Load(Graphics * graphics, char* fileName, DWORD transparent, D3DFORMAT format)
	{
		//Free old stuff if it exists
		Free();

		this->graphics = graphics;

		if(graphics == NULL || fileName == NULL)
			return false;

		if(graphics->GetDeviceCOM() == NULL)
			return false;

		if(FAILED(D3DXCreateTextureFromFileEx(graphics->GetDeviceCOM(), fileName,
			D3DX_DEFAULT,
			D3DX_DEFAULT, 
			D3DX_DEFAULT,
			0,
			format, 
			D3DPOOL_MANAGED, 
			D3DX_FILTER_TRIANGLE, 
			D3DX_FILTER_TRIANGLE,
			transparent, 
			NULL, 
			NULL, 
			&texture)))
			return false;

		D3DSURFACE_DESC d3dsd;
		texture->GetLevelDesc(0, &d3dsd);

		width = d3dsd.Width;
		height = d3dsd.Height;

		center.x = width / 2.0f;
		center.y = height / 2.0f;
		center.z = 0.0f;

		return true;
	}

	bool Texture::Create(Graphics * graphics, DWORD width, DWORD height, D3DFORMAT format)
	{
		Free();
		this->graphics = graphics;

		if(graphics == NULL)
			return false;

		return SUCCEEDED(graphics->GetDeviceCOM()->CreateTexture(width, height, 0, 0, format, D3DPOOL_MANAGED, &texture, NULL));	
	}

	bool Texture::Create(Graphics *graphics, IDirect3DTexture9 *texture)
	{
		Free();

		this->graphics = graphics;
		if(graphics == NULL)
			return false;

		D3DLOCKED_RECT srcRect, destRect;
		D3DSURFACE_DESC desc;

		if(texture == NULL)
			return true;

		texture->GetLevelDesc(0, &desc);
		width = desc.Width;
		height = desc.Height;

		center.x = width / 2.0f;
		center.y = height / 2.0f;
		center.z = 0.0f;

		if(FAILED(graphics->GetDeviceCOM()->CreateTexture(width, height, 0, 0, desc.Format, D3DPOOL_MANAGED, &texture, NULL)))
			return false;

		texture->LockRect(0, &srcRect, NULL, D3DLOCK_READONLY);
		this->texture->LockRect(0, &destRect, NULL, 0);

		memcpy(destRect.pBits, srcRect.pBits, srcRect.Pitch * height);

		this->texture->UnlockRect(0);
		texture->UnlockRect(0);

		return true;
	}

	bool Texture::Free()
	{
		ReleaseCOM(texture);
		graphics = NULL;
		width = height = 0;

		return true;
	}

	bool Texture::Loaded() const
	{
		return texture == NULL;
	}

	long Texture::GetWidth() const
	{
		return width;
	}
	long Texture::GetHeight() const
	{
		return height;
	}

	D3DFORMAT Texture::GetFormat() const
	{
		if(texture == NULL)
			return D3DFMT_UNKNOWN;

		D3DSURFACE_DESC d3dsd;

		if(FAILED(texture->GetLevelDesc(0, &d3dsd)))
			return D3DFMT_UNKNOWN;

		return d3dsd.Format;
	}

	bool Texture::Blit(long destX, long destY, long srcX, long srcY, long width, long height,
		float scaleX, float scaleY, float rotation, D3DCOLOR color)
	{
		if(texture == NULL || graphics == NULL)
			return false;

		ID3DXSprite* sprite = graphics->GetSpriteCOM();
		if(sprite == NULL)
			return false;

		if(width == 0)
			width = this->width;
		if(height == 0)
			height = this->height;

		RECT rect;
		rect.left = srcX;
		rect.top = srcY;
		rect.right = rect.left + width;
		rect.bottom = rect.top + height;

		D3DXMATRIX texScaling;
		D3DXMATRIX rot;
		D3DXMATRIX trans;
		D3DXMatrixScaling(&texScaling, scaleX, scaleY, 0.0f);
		D3DXMatrixTranslation(&trans, (float)destX, (float)destY, 0.0f);
		D3DXMatrixRotationZ(&rot, rotation);
		HR(sprite->SetTransform(&(texScaling * rot * trans)));
		//HR(sprite->SetTransform(&(rot)));

		D3DXVECTOR3 position = D3DXVECTOR3((float)destX, (float)destY, 0.0f);
		HR(sprite->Draw(texture, &rect, &center, 0, D3DCOLOR_XRGB(255, 255, 255)));
		HR(sprite->Flush());

		return true;

	}

}